#include <iostream>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <string>
#include <sys/wait.h>
#include <algorithm>
//fork之后子进程是能够拿到父进程的数据的-- 有写时拷贝，感觉不算是通信
using namespace std;
const int size = 1024;

string getOtherMessage()
{
    static int cnt = 0;
    string messageid = to_string(cnt);
    cnt++;
    pid_t self_id = getpid();
    string stringpid = to_string(self_id);
    return "messageid: "+messageid+"my pid: "+stringpid;
}
void SubProcessWrite(int wfd)
{
    string message = "father, I am you son process.";
    while(true)
    {
        string info = message + getOtherMessage();
        write(wfd,message.c_str(),message.size());
        sleep(1);
    }
}
void FatherRead(int rfd)
{
    char buffer[size];
    while(true)
    {
        size_t n = read(rfd,buffer,sizeof buffer);
        if(n > 0)
        {
            buffer[n] = '\0';
            cout<<"father get message: "<<buffer<<endl;
        }
    }
}
int main()
{
    //1. 创建管道
    int pipefd[2];
    int n = pipe(pipefd);//输出型参数，rfd，wfd
    if(n != 0)
    {
        //说明创建失败了
        cerr<<"errno: "<<errno<<": "<<"errstring:" << strerror(errno)<<endl;
        return 1;
    }
    //说明创建成功了
    //pipefd[0]->0->r 永远对应的是读的权限  pipefd[1]->1->w 永远对应的是写的权限
    //列举一个好记的方法，0就像是一张嘴，对应的是读，而1则像一直钢笔，对应的就是写
    cout<<"pipefd[0]: "<<pipefd[0]<<", "<<"pipefd[1]: "<<pipefd[1]<<endl;
    sleep(1);
    //2.创建子进程
    //3.关闭不需要的文件描述符
    pid_t id = fork();
    if(id == 0)
    {
        cout<<"子进程关闭不需要的fd，准备发动消息了"<<endl;
        sleep(1);
        //这是一个子进程(child)
        //子进程 -- write
        close(pipefd[0]);
        SubProcessWrite(pipefd[1]);
        close(pipefd[1]);
        exit(0);
    }
    //这里是父进程(parent)
    //父进程 -- read
    close(pipefd[1]);
    FatherRead(pipefd[0]);
    close(pipefd[0]);
    pid_t rid = waitpid(id,nullptr,0);
    if(rid>0)
    {
        cout<<"wait child process done"<<endl;
    }
    return 0;
}
/*
1.匿名管道：只能用来进行具有血缘关系的进程之间进行通信，常用于父子进程之间的通信
2.管道内部，自带进程之间的同步的机制（多执行流执行代码的时候，具有明显的顺序性！！）

*/